package com.doubleview;


import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.junit.Test;

import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

/**
 * @author huchengchao@kuaishou.com
 * Created on 2021-11-19
 */
public class GroovyClassLoaderExample {

    String groovyClassPath = "/Users/huchengchao/project/doubleview/java-awesome-demo/language-samples/groovy/src/main/groovy/com/doubleview/SimpleClass.groovy";
    String javaClassPath = "/Users/huchengchao/project/doubleview/java-awesome-demo/language-samples/groovy/src/main/groovy/com/doubleview/Helper.java";

    String groovyPath = "/Users/huchengchao/project/doubleview/java-awesome-demo/language-samples/groovy/src/main/groovy/com/doubleview/SimpleScript.groovy";

    ExecutorService executorService = Executors.newFixedThreadPool(1);

    @Test
    public void testThreadInterrupt() {
        try {
            Future future = executorService.submit(() -> {
                try {
                    GroovyClassLoader loader = new GroovyClassLoader();
                    Class hello = loader.parseClass(new File(groovyPath));
                    Script script = (Script) hello.getDeclaredConstructor().newInstance();
                    script.setProperty("language", "java");
                    script.run();
                } catch (Exception e) {
                    System.out.println(e.getClass());
                    e.printStackTrace();
                }
            });
            Thread.sleep(2000);
            future.cancel(true);
            Thread.sleep(10000);
            System.out.println("end");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testBaseScript() {
        try {
            CompilerConfiguration config = new CompilerConfiguration();
            config.setScriptBaseClass(DelegatingScript.class.getName());
            GroovyClassLoader loader = new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), config, true);
            Class hello = loader.parseClass(new File(groovyPath));
            DelegatingScript script = (DelegatingScript) hello.getDeclaredConstructor().newInstance();
            script.setProperty("language", "java");
            script.run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testParseGroovyClass() {
        try {
            GroovyClassLoader loader = new GroovyClassLoader();
            Class hello = loader.parseClass(new File(groovyClassPath));
            GroovyObject object = (GroovyObject) hello.getDeclaredConstructor().newInstance();
            Object res = object.invokeMethod("sayHello", null);
            System.out.println(res);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Test
    public void testParseGroovyClass2() {
        try {
            GroovyClassLoader loader = new GroovyClassLoader();
            Class fileCreator = loader.parseClass("println \"Welcome to $language\"");
            Script object = (Script) fileCreator.getDeclaredConstructor().newInstance();
            object.getBinding().setVariable("language", "java");
            System.out.println(object.run());


        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Test
    public void testParseJavaClass() {
        try {
            GroovyClassLoader loader = new GroovyClassLoader();
            Class fileCreator = loader.parseClass(new File(javaClassPath));
            GroovyObject object = (GroovyObject) fileCreator.getDeclaredConstructor().newInstance();
            System.out.println(object);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
